package com.cgene.game;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.media.MediaPlayer;
import android.view.View;

/**
 * RPG描写のViewクラス
 *
 * 背景画像提供元：
 * 佐和多里様 URL：http://iyukiainosaka.kitunebi.com/
 */
class MiyagiQuestView extends View {

    public int displayWidth;							//	画面幅
    public int displayHeight;							//	画面高さ

    public boolean Flag_LongTouch = false;				// ロングタッチイベントステータス
    public int TouchStatus = -1;						// タッチイベントステータス
    final static public int TouchStatus_UP = 1;			// タッチイベント上
    final static public int TouchStatus_DOWN = 2;		// タッチイベント下
    final static public int TouchStatus_LEFT = 3;		// タッチイベント左
    final static public int TouchStatus_RIGHT = 4;		// タッチイベント右
    final static public int TouchStatus_TAP = 5;		// タッチイベントタップ

    /** ステータス定義情報 */
    final static private int STATUS_WAIT = -1;			//	何もしない。
    final static private int STATUS_START = 0;			//	起動～タイトル表示まで
    final static private int STATUS_TITLE = 1;			//	タイトル表示
    final static private int STATUS_ROLL = 2;			//	ゲームロール
    final static private int STATUS_MAP = 3;			//	フィールドマップ
    final static private int STATUS_MENU = 4;			//	メニュー
    final static private int STATUS_BATTLE = 5;			//	戦闘シーン
    final static private int STATUS_ENDING = 8;			//	エンディング
    final static private int STATUS_GAMEOVER = 9;		//	ゲームオーバー
    final static private int STATUS_ERROR = 9999;		//	エラー

    private int isSave = 0;

    /** ステータス情報 */
    private int status = STATUS_START;					//	ゲームステータス
    @SuppressWarnings("unused")
	private int exStatus = -1;							//	前のステータス（今回は利用せず）
    /** スリープ変数 */
	private long sleep = 100;							//	処理を停止させるミリ秒

	/** プレイヤー情報 */
	private int level = 1;								//	レベル
	private int maxHp = 0;								//	最大ヒットポイント
	private int hp = 0;									//	ヒットポイント
	private float dngHP = 1;
	private int str = 0;								//	攻撃力
	private int def = 0;								//	防御力
	private int spd = 0;								//	スピード
	private int exp = 0;								//	現在の経験地
	private int nextExp = 0;							//	次の経験値
	private int maxSp = 0;								//	最大スキルポイント
	private int sp = 0;									//	スキルポイント
	private int maxspup;								//	LVアップ時の成長ポイント

	private int FLAG_SENDAI_WEAPON = 0;					//	フラグ：武器
	private int FLAG_SENDAI_ARMOR = 0;					//	フラグ：鎧
	private int FLAG_SENDAI_SHIELD = 0;					//	フラグ：盾
	private int FLAG_ITEM1 = 0;							//	フラグ：アイテム１
	private int FLAG_ITEM2 = 0;							//	フラグ：アイテム２
	private int FLAG_ITEM3 = 0;							//	フラグ：アイテム３
	private int FLAG_BOSS1 = 0;							//	フラグ：ボスキャラ１

	/** タイトル画面用パラメータ */
	private int titleSelectedIndex = 0;					//	タイトルメニューの選択値
	private int playerDrawIndex = 0;					//	プレイヤーのアニメーション値（マップでも利用）
    private Bitmap titleImage;							//	タイトル画像
    private Bitmap[][] playerImage = new Bitmap[4][2];	//	プレイヤー画像配列（マップでも利用）
    private boolean startFlag = true;					//	初回プレイ時のフラグ

	/** ロール画面用パラメータ */
	private String rollMsgTxt[] = new String[0];		//	ロール用メッセージ
	private int rollMarginX = 10;						//	表示ｘ座標
	private int rollMsgPosY = 0;						//	表示ｙ座標

	/** フィールドマップ画面用パラメータ */
	final static private String MAP_DEF = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";	//	地図定義
    final static private int PLAYER_DIRECTION_DOWN = 0;		//	プレイヤーの向き（下）
    final static private int PLAYER_DIRECTION_LEFT = 1;		//	プレイヤーの向き（左）
    final static private int PLAYER_DIRECTION_RIGHT = 2;	//	プレイヤーの向き（右）
    final static private int PLAYER_DIRECTION_UP = 3;		//	プレイヤーの向き（上）
    private Bitmap[] fldImage = new Bitmap[36];				//	フィールド画像配列 28+NPC8=36
    private Bitmap mapImage = null;							//	地図描写用全体画像
	private int[][] filedMapInt = new int[0][0];			//	地図情報配列
	private String filedMapCannotMoveTxt = "";				//	移動不可地図情報テキスト
	@SuppressWarnings("unchecked")
	private HashMap mapActionMap = new HashMap();			//	地図上でのアクションを管理するMap変数
	private int cannotMoveImageInt = -1;					//	地図の範囲外の場合に表示したい画像情報

	private int playerMapPosX = 0;							//	プレイヤーの地図上のｘ座標
	private int playerMapPosY = 0;							//	プレイヤーの地図上のｙ座標
	private int playerDrawPosX = 0;							//	プレイヤーの表示位置。必ず中央です。
	private int playerDrawPosY = 0;							//	プレイヤーの表示位置。必ず中央です。
	private int mapMarginX = 0;								//	画面上に描写する地図のマージンｘ座標
	private int mapMarginY = 0;								//	画面上に描写する地図のマージンｙ座標
	private int fieldMapImageWidth = 24;					//	フィールド画像の幅
	private int fieldMapWidth = 80;//40;					//	定義されている地図の最大横幅
	private int fieldMapHeight = 80;//40;					//	定義されている地図の最大縦幅
	private int playerDirection = PLAYER_DIRECTION_DOWN;	//	プレイヤーの向き
	private int statusDrawPosY = 0;							//	ステータス表示をするｙ座標
	private int helpMsgTxtIndex = 0;						//	補足テキストの、描写位置
	private String helpMsgTxt = "";							//	補足テキスト
	static int map = R.string.map;							//	初期マップ番号
//	private int mapNo = 0;									//	現在マップ番号（現在マップ番号を保存するのであれば使用）
	private static int encount = 40;						//	敵モンスター出現確率
	private boolean encFlag = true;							//	モンスター発生フラグ

	/** 戦闘シーン画面用パラメータ */
	public Enemy[] enemy = new Enemy[0];					//	敵のクラス
	public int battleMarginX = 0;							//	戦闘シーンのメッセージ枠描写のマージンｘ座標
	public int battleMarginY = 0;							//	戦闘シーンのメッセージ枠描写のマージンｙ座標
	private String[] battleMsgTxts = new String[4];			//	戦闘メッセージ
	private String[] battleMsgMasterTxts = new String[0];	//	戦闘メッセージマスタテキスト
	private int battleMsgTxtIndex = 0;						//	戦闘メッセージマスタのインデックス値
	private int battleMenuSelectedIndex = 0;				//	戦闘メニューの選択値
	private int battleMenuSelectedMinusX = 0;				//	戦闘メニュー選択表示のための、マージン値
	private int battleMenuSelectedPlusX = 0;				//	戦闘メニュー選択表示のための、マージン値
	private int battleEnemySelectedIndex = -1;				//	戦闘シーンで、敵の選択のインデックス値
	private String[] battleActions = new String[0];			//	戦闘シーンにおける、アクションテキスト配列
	private Bitmap[] batteImages;							//	タイトル画像
	private Bitmap batteImage;
	public boolean selectFlag = false;						//	全体攻撃用選択フラグ
	public boolean paintFlag = false;						//	全体攻撃用選択フラグ
	public int reqSpec = 3;									//	特殊攻撃に必要なSP
	public int reqCure = 2;									//	回復に必要なSP

	/** エラー画面用パラメータ */
	private String errorTxt = "";							//	エラーメッセージ

	/** 共通変数 */
	private int drawFontSize = 14;							//	描写用のフォントサイズ
	private int count = 0;									//	処理カウント変数
	@SuppressWarnings("unused")
	private long keyPressedTime = 0;						//	キーイベント操作用変数。（押下時の時刻を保持させておく）

	/** BGM用変数 */
    public MediaPlayer mp_Bgm = null;						// BGM用インスタンス
    public MediaPlayer mp_Se = null;						// SE用インスタンス

	private MiyagiQuest activity = null;

	/**
     * Miyagi Quest の表示処理用クラス コンストラクタ
     * 初期化などの処理を行う。
	 */
	@SuppressWarnings("unchecked")
 	public MiyagiQuestView(Context context, MiyagiQuest act) {

		super(context);
		activity = act;

		setFocusable(true);

		//	タイトル画像読み込み
		Resources r = getResources();
		titleImage = BitmapFactory.decodeResource(r, R.drawable.titlemiyagi);

		//TODO 戦闘時背景画像読み込み
		batteImages = new Bitmap[4];
		batteImages[0] = BitmapFactory.decodeResource(r, R.drawable.battle_01);
		batteImages[1] = BitmapFactory.decodeResource(r, R.drawable.battle_02);
		batteImages[2] = BitmapFactory.decodeResource(r, R.drawable.battle_03);
		batteImages[3] = BitmapFactory.decodeResource(r, R.drawable.battle_04);

		//	マップ画像の読み込み
		//	フィールド名と、実際値が異なるので、reflectionを利用。
		//	reflection とは、フィールド名などから、その値を取得するための機能。
		try {
			//	どのクラスから取得するかを指定
			Class cls = Class.forName("com.cgene.game.R$drawable");
			for (int i = 1, idx = 0; i <= 7; i ++) {
				for (int j = 1; j <= 4; j ++) {
					String fldName = "field_" + i + j;
					fldImage[idx] = BitmapFactory.decodeResource(r, getResouceInt(cls, fldName));
					idx ++;
				}
			}

			//TODO NPCキャラ（マップチップと同じ扱い）読み込み
			fldImage[28] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_76" ));
			fldImage[29] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_77" ));
			fldImage[30] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_78" ));
			fldImage[31] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_79" ));
			fldImage[32] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_80" ));
			fldImage[33] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_81" ));
			fldImage[34] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_82" ));
			fldImage[35] = BitmapFactory.decodeResource(r, getResouceInt(cls,"field_83" ));

			//	上記の処理は、fldImage[idx] = BitmapFactory.decodeResource(r, R.drawable.filed_11); としても同じだが、
			//	R.drawable.filed_11 を、28個も記述するのが、面倒なので、リフレクションで簡易化している。

			//	プレイヤー画像の読み込み。フィールド名と、実際値が異なるので、reflectionを利用。
			char c[] = {'b', 'l', 'r', 'u'};
			for (int i = 0; i < c.length; i ++) {
				for (int j = 0; j < 2; j ++) {
					String fldName = "hero_" + c[i] + (j+1);
					playerImage[i][j] = BitmapFactory.decodeResource(r, getResouceInt(cls, fldName));
				}
			}

		} catch (Exception e) {
			android.util.Log.e(DebugLog.TAG, e.toString());
		}
		//	初期化が終わったので、ステータスを、タイトルに設定する。
		setStatus(STATUS_TITLE, true);

		TouchStatus = 0;
	}

	/**
     * リフレクションのための、サポートメソッド。指定されたフィールド名のint値が返る。
     * @param	cls			対象クラス
     * @param	fieldName	フィールド名
     * @return	設定されている、int値を返す。
	 */
	@SuppressWarnings("unchecked")
	public int getResouceInt(Class cls, String fieldName) throws Exception {
		if (cls == null) {
			cls = Class.forName("com.cgene.game.R$drawable");
		}
		Field fld = cls.getField(fieldName);
		return fld.getInt(cls.newInstance());
	}

	/**
     * 処理停止のミリ秒を返す。ステータスごとに描写の速度が異なるので、
     * ※public 変数にしてしまえば、必要なし。直接参照は可能。
     * @return	設定されている、停止ミリ秒を返す。
	 */
	public long getSleep() {
		return sleep;
	}

	/**
     * ステータスをセットします。
     * @param	sts		設定するステータス値
     * @param	init	初期化するかのフラグ
	 */
	private void setStatus(int sts, boolean init) {
		exStatus = status;
		status = sts;
		if (init) {
			try {
				init(sts);
			} catch (Exception e) {
				errorTxt = e.toString();
				setStatus(STATUS_ERROR, false);
			}
		}
	}

	/**
     * 処理を停止させる。
     * @param	time	停止させたいミリ秒
	 */
	public void sleep(long time) {
		try {
			Thread.sleep(time);
		} catch (Exception e) {
		}
	}

	/**
     * 初期化の処理
     * @param	sts		初期化を行うステータス
	 */
	@SuppressWarnings("unchecked")
	public void init(int sts) throws Exception {
		DebugLog.printin("init(" + sts + ") start");
		count = 0;
		Resources r = getResources();
        switch (sts) {
        case STATUS_TITLE	:		//	タイトル描写のためのデータ初期化
        	sleep = 100;
        	drawFontSize = 20;
        	titleSelectedIndex = 0;
        	playerDrawIndex = 0;
        	break;
        case STATUS_ROLL	:		//	ゲームロール描写のためのデータ初期化
        	rollMarginX = 20;
        	sleep = 50;
        	//	ゲームロールのメッセージは、roll_msg にて、リソース管理されています。
        	rollMsgTxt = MyUtil.split(r.getString(R.string.roll_msg), "|");
        	drawFontSize = 24;
        	rollMsgPosY = displayHeight;
        	break;
        case STATUS_MAP		:		//	マップ描写のためのデータ初期化
        	//	地図情報をリソースから、取得します。
    		//String mapTxt = r.getString(R.string.map);
    		String mapTxt = r.getString(map);	//マップ遷移対応！
        	//	地図情報は、スペース区切りなので、各行ごとに分割させます。
    		String mapTxts[] = MyUtil.split(mapTxt, " ");
    		//	フィールドマップの定義されている地図の最大幅を設定します。
    		fieldMapWidth = mapTxts[0].length();
    		fieldMapHeight = mapTxts.length;		//	地図情報の最後に、改行やスペースが入っていると変になるので注意。
    		//	地図情報から、実際の値（int値）を設定していきます。
    		filedMapInt = new int[fieldMapHeight][fieldMapWidth];
    		for (int y = 0; y < fieldMapHeight; y ++) {
    			for (int x = 0; x < fieldMapWidth; x ++) {
    				int idx = MAP_DEF.indexOf(mapTxts[y].charAt(x));
    				if (idx == -1) idx = 0;
    				else if (idx >= fldImage.length) idx = 0;
    				filedMapInt[y][x] = idx;
    			}
    		}
    		//	地図上のアクション（SAVE, CURE）などのアクションを設定していきます。
    		if (true) {
    			Class cls = Class.forName("com.cgene.game.R$string");
	    		for (int i = 0; i < MAP_DEF.length(); i ++) {
	    			try {
	    				int k = getResouceInt(cls, "map_action_" + MAP_DEF.charAt(i));
	    				String act = r.getString(k);
	    				if (act != null) {
	    					mapActionMap.put(String.valueOf(i), act);
	    				}
	    			} catch (Exception e) {
	    			}
	    		}
    		}
    		//	地図情報の中で、移動できないフィールドテキストを設定する。
    		filedMapCannotMoveTxt = r.getString(R.string.map_cannot_move);
    		cannotMoveImageInt = MAP_DEF.indexOf(filedMapCannotMoveTxt.charAt(0));

    		//	マップ表示マージンの初期化
    		mapMarginX = (displayWidth - fldImage[0].getWidth()*13)/2;
    		mapMarginY = mapMarginX;

    		//マップ表示時の効果音
			try {
				MyUtil.PlaySound_SE(activity, MyUtil.SE_IN_OUT);
			} catch (Exception e) {
				e.printStackTrace();
			}

    		//	フィールド一つの画像幅を設定
    		fieldMapImageWidth = fldImage[0].getWidth();

    		//	プレイヤーの表示位置を設定。常に、マップ中央です。
    		playerDrawPosX = mapMarginX + fieldMapImageWidth*6;
    		playerDrawPosY = mapMarginY + fieldMapImageWidth*6;

    		//	プレイヤーの初期化
    		playerMapPosX = mapTxts[0].length()/2;
    		playerMapPosY = mapTxts.length/2;
    		playerDirection = PLAYER_DIRECTION_DOWN;
    		playerDrawIndex = 0;

    		//	プレイヤーステータス情報の初期化
    		if(startFlag){
	    		drawFontSize = 20;

	    		level   = 1;
	    		maxHp   = 32;			//	最大ヒットポイント
	    		hp      = 32;			//	ヒットポイント
	    		str     = 9;			//	攻撃力
	    		def     = 8;			//	防御力
	    		spd     = 6;			//	スピード
	    		exp     = 0;			//	経験値
	    		nextExp = 30;
	    		maxSp   = 10;			//	最大スキルポイント
	    		sp      = 10;			//	スキルポイント

	    		//	最初に表示するヘルプテキストをリソースから設定します。
	    		helpMsgTxt = r.getString(R.string.map_help_msg);
	    		helpMsgTxtIndex = -5;

	    		//初回プレイフラグの変更
	    		startFlag = false;
    		}

    		//	プレイヤーステータス（ＨＰなど）を表示するｙ座標を設定します。
    		statusDrawPosY = mapMarginY*2 + 4 + fieldMapImageWidth*13;


    		//	地図画像の初期化
    		mapImage = Bitmap.createBitmap(fieldMapImageWidth*13, fieldMapImageWidth*13, Bitmap.Config.ARGB_8888);
    		Canvas canvas = new Canvas(mapImage);
    		initMapImage(canvas);

        	sleep = 100;

        	break;
        case STATUS_MENU	:	//	メニュー描写のためのデータ初期化（今回は、利用なし）
        	break;
        case STATUS_BATTLE	:	//	戦闘シーン描写のためのデータ初期化

        	//	敵の数をランダムで設定します。
        	int max = 2+level;
        	if (max > 6) max = 6;
        	int k = MyUtil.nextInt(max)+1;	//	1 - 3 まで

    		if(FLAG_BOSS1 == 1) k = 1;		//ボスキャラ用

        	enemy = new Enemy[k];

        	//	戦闘メッセージを初期化します。
    		battleMsgTxts = new String[4];
    		battleMsgMasterTxts = new String[k];

    		//	敵の情報とメッセージを初期化します。
        	for (int i = 0; i < enemy.length; i ++) {

        		//レベルに応じた敵の選出
        		//TODO モンスターの出現率などのバランスを調節！
        		k = MyUtil.nextInt(level);	//レベルで乱数調節！
        		if(FLAG_BOSS1 == 1) k = -1;		//ボスキャラ用
        		String txt ="";
        		switch(k){
    				case 0:
    					txt = r.getString(R.string.enemy_1);break;
    				case 1:
        				txt = r.getString(R.string.enemy_2);break;
    				case 2: case 3:
        				txt = r.getString(R.string.enemy_2);break;
    				case 4: case 5:
        				txt = r.getString(R.string.enemy_3);break;
    				case 6: case 7:
        				txt = r.getString(R.string.enemy_4);break;
    				case 8: case 9:
        				txt = r.getString(R.string.enemy_5);break;
    				case 10: case 11:
        				txt = r.getString(R.string.enemy_6);break;
    				case 12: case 13:
        				txt = r.getString(R.string.enemy_7);break;
    				case 14: case 15:
        				txt = r.getString(R.string.enemy_8);break;
        			case -1:
        				txt = r.getString(R.string.enemy_99);break;
        			default:
        				txt = r.getString(R.string.enemy_8);break;
        		}

        		enemy[i] = new Enemy(this, txt, i, enemy.length);
        		battleMsgMasterTxts[i] = enemy[i].name + "が現れた！";
        	}
        	battleMarginX = mapMarginX;
        	battleMarginY = -8;
    		drawFontSize = 20;

    		//	描写のための変数処理のため、paintを初期化します。
    		Paint paint = new Paint();
            paint.setStyle(Paint.Style.FILL);
    		paint.setStrokeWidth(1);
    		paint.setTextSize(drawFontSize);

    		//	戦闘メニューで必要な数値の初期化
    		battleMenuSelectedIndex = 0;
			battleMenuSelectedMinusX = 5 + (int)paint.measureText("≫");
			battleMenuSelectedPlusX = 5 + (int)paint.measureText("戦　う");

			battleEnemySelectedIndex = -1;
			battleActions = new String[0];

    		battleMsgTxtIndex = -1;
        	break;

        case STATUS_ENDING	:	//	ゲームオーバー描写のためのデータ初期化
        	sleep = 1000;
        	drawFontSize = 40;
        	rollMarginX = 20;
        	//	ゲームロールのメッセージは、roll_msg にて、リソース管理されています。
        	rollMsgTxt = MyUtil.split(r.getString(R.string.roll_msg2), "|");
        	drawFontSize = 24;
        	rollMsgPosY = displayHeight;
        	break;

        case STATUS_GAMEOVER	:	//	ゲームオーバー描写のためのデータ初期化
        	sleep = 1000;
        	drawFontSize = 40;
        	break;
        case STATUS_ERROR	:		//	エラー描写のためのデータ初期化
    		drawFontSize = 20;
        	break;
        }
		DebugLog.printin("init(" + sts + ") done");
	}

	/**
     * マップの指定範囲内かどうかを判定する。
     * @param	x	地図のｘ座標
     * @param	y	地図のｙ座標
     * @return		範囲内かどうかのフラグ
	 */
	private boolean isDrawableMap(int x, int y) {
		if ( x < 0 || y < 0 || x >= fieldMapWidth || y >= fieldMapHeight) {
			return false;
		} else {
			int k = filedMapInt[y][x];
			if (k < 0 || k >= fldImage.length) {
				return false;
			} else {
				return true;
			}
		}
	}

	/**
     * タイトルを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void title(Canvas canvas, Paint paint) {
		if(isSave==0){
			String[] data = MyUtil.split(load(), ",");
			//TODO 保存項目数により異なる！！
			if (data.length > 10){
				try {
					//	保存データから、各値を初期化
					int k = 0;
					level = Integer.parseInt(data[k++]);
					maxHp = Integer.parseInt(data[k++]);
					hp = Integer.parseInt(data[k++]);
					maxSp = Integer.parseInt(data[k++]);
					sp = Integer.parseInt(data[k++]);
					str = Integer.parseInt(data[k++]);
					def = Integer.parseInt(data[k++]);
					spd = Integer.parseInt(data[k++]);
					exp = Integer.parseInt(data[k++]);
					nextExp = Integer.parseInt(data[k++]);
					map = Integer.parseInt(data[k++]);
					playerMapPosX = Integer.parseInt(data[k++]);
					playerMapPosY = Integer.parseInt(data[k++]);

					//TODO 各種イベントフラグ
					FLAG_SENDAI_WEAPON = Integer.parseInt(data[k++]);
					FLAG_SENDAI_ARMOR  = Integer.parseInt(data[k++]);
					FLAG_SENDAI_SHIELD = Integer.parseInt(data[k++]);
					FLAG_ITEM1  = Integer.parseInt(data[k++]);
					FLAG_ITEM2  = Integer.parseInt(data[k++]);
					FLAG_ITEM3  = Integer.parseInt(data[k++]);
				} catch (Exception e) {
					//	処理中にエラーが発生したら、New Gameへ
					setStatus(STATUS_ROLL, true);
				}
				isSave=2;
			}
			if(isSave==0)isSave=1;
		}
		//	タッチイベント処理
		switch (TouchStatus) {
		case TouchStatus_UP:
			titleSelectedIndex--;
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_DOWN:
			titleSelectedIndex++;
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_TAP:
			//	選択キーでの処理
			sleep(500);
			TouchStatus = -1;
			if (titleSelectedIndex == 1) {	//	Continueが選択された場合
				//	保存データを読み込み、[,]で分割。
				String[] data = MyUtil.split(load(), ",");
				//TODO 保存項目数により異なる！！
				if (data.length < 19) {
					//	データがないか、不正であれば、New Gameへ
					setStatus(STATUS_ROLL, true);
				} else {
					//	データがあれば、ステータスをMAPに設定し、初期化）
					setStatus(STATUS_MAP, true);
					try {
						//	保存データから、各値を初期化
						int k = 0;
						level = Integer.parseInt(data[k++]);
						maxHp = Integer.parseInt(data[k++]);
						hp = Integer.parseInt(data[k++]);
						maxSp = Integer.parseInt(data[k++]);
						sp = Integer.parseInt(data[k++]);
						str = Integer.parseInt(data[k++]);
						def = Integer.parseInt(data[k++]);
						spd = Integer.parseInt(data[k++]);
						exp = Integer.parseInt(data[k++]);
						nextExp = Integer.parseInt(data[k++]);
						map = Integer.parseInt(data[k++]);
						playerMapPosX = Integer.parseInt(data[k++]);
						playerMapPosY = Integer.parseInt(data[k++]);

						//TODO 各種イベントフラグ
						FLAG_SENDAI_WEAPON = Integer.parseInt(data[k++]);
						FLAG_SENDAI_ARMOR  = Integer.parseInt(data[k++]);
						FLAG_SENDAI_SHIELD = Integer.parseInt(data[k++]);
						FLAG_ITEM1  = Integer.parseInt(data[k++]);
						FLAG_ITEM2  = Integer.parseInt(data[k++]);
						FLAG_ITEM3  = Integer.parseInt(data[k++]);

						//初回プレイ時フラグ
						startFlag = false;

			    		initMapImage(new Canvas(mapImage));
					} catch (Exception e) {
						//	処理中にエラーが発生したら、New Gameへ
						setStatus(STATUS_ROLL, true);
					}
				}
			} else {	//	New Gameが選択されました。
				setStatus(STATUS_ROLL, true);
			}
			//	処理は、ここで終了。（キーイベント処理で終了です。）
			return;
		}
		//	タイトル選択インデックスの処理
		if (titleSelectedIndex < 0) titleSelectedIndex = 1;
		else if (titleSelectedIndex > 2) titleSelectedIndex = 0;

		//	描写処理
		int x = (displayWidth-titleImage.getWidth())/2;
		int y = 10;
		canvas.drawBitmap(titleImage, x, y, paint);

		paint.setTextSize(42);
		y += 58 + titleImage.getHeight();

        paint.setColor(Color.WHITE);
        canvas.drawText("New Game", 80, y, paint);
        canvas.drawText("Continue", 80, y + 60, paint);
        if(isSave==2){
        	paint.setTextSize(20);
        	canvas.drawText("Lv:"+level, 150, y + 90, paint);
        	canvas.drawText("HP:"+maxHp, 200, y + 90, paint);
        	canvas.drawText("EXP:"+exp, 270, y + 90, paint);
        }
        //	選択されている側にプレイヤー画像を表示されます。
        if (titleSelectedIndex == 0) {
    		canvas.drawBitmap(playerImage[2][playerDrawIndex], 20, y-36, paint);
        } else {
    		canvas.drawBitmap(playerImage[2][playerDrawIndex], 20, y+60-36, paint);
        }
        //	プレイヤーのアニメーション変更。countで、早すぎないように変更させる。
        if (count%3 == 0) playerDrawIndex = (playerDrawIndex+1)%2;
	}

	/**
     * ゲームロールを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void roll(Canvas canvas, Paint paint) {
		//	タッチイベント処理
		switch (TouchStatus) {
		case TouchStatus_TAP:
			if (rollMsgPosY < 50) {
				//	表示位置が、50pixより小さければ、選択キーで、次のステータス（マップ）へ
				sleep(500);
				TouchStatus = -1;
				setStatus(STATUS_MAP, true);
				return;
			}
		}
		//	描写位置の下限
		if (rollMsgPosY < 50) rollMsgPosY = 50;

		//	ロールメッセージを表示させます。
		paint.setTextSize(19);
		for (int i = 0; i < rollMsgTxt.length; i ++) {
			paint.setColor(Color.WHITE);
			canvas.drawText(rollMsgTxt[i], rollMarginX, rollMsgPosY + i*(drawFontSize+5), paint);
		}
		//	ロールメッセージが、下限になった場合のみ、「Hit Key」を表示させて、次を促します。
		if (rollMsgPosY == 50) {
			paint.setColor(Color.WHITE);
			canvas.drawText("Please press Hit Key", rollMarginX, displayHeight-drawFontSize-20, paint);
			paint.setColor(Color.BLUE);
			canvas.drawText("Please press Hit Key", rollMarginX-1, displayHeight-drawFontSize-20-1, paint);
		}
		rollMsgPosY -= 5;
	}

	/**
     * 地図画像を初期化します。
	 * @param	canvas	描写キャンバスクラス
	 */
	public void initMapImage(Canvas canvas) {
		//	地図の描写
		for (int y = playerMapPosY - 6, j = 0; y < playerMapPosY + 7; y ++, j ++) {
			for (int x = playerMapPosX - 6, i = 0; x < playerMapPosX + 7; x ++, i ++) {
				if (isDrawableMap(x, y)) {
					canvas.drawBitmap(fldImage[filedMapInt[y][x]], i*fieldMapImageWidth, j*fieldMapImageWidth, new Paint());
				} else {
					canvas.drawBitmap(fldImage[cannotMoveImageInt], i*fieldMapImageWidth, j*fieldMapImageWidth, new Paint());
				}
			}
		}
	}

	/**
     * 地図上で、指定方向に動いたかを判定します。
	 * @param	direction	移動方向
	 */
	public boolean mapMoved(int direction) {
		boolean moved = true;
		//	現在値をバックアップ
		int prevx = playerMapPosX;
		int prevy = playerMapPosY;
		playerDirection = direction;
		switch (direction) {
		case PLAYER_DIRECTION_UP : 		//	上を移動したい場合
			playerMapPosY --;
			if (playerMapPosY < 0) {	//	できませんでした。
				playerMapPosY = 0;
				moved = false;
			}
			break;
		case PLAYER_DIRECTION_DOWN : 	//	下を移動したい場合
			playerMapPosY ++;
			if (playerMapPosY >= fieldMapHeight) {	//	できませんでした。
				playerMapPosY = fieldMapHeight-1;
				moved = false;
			}
			break;
		case PLAYER_DIRECTION_LEFT : 	//	左に移動したい場合
			playerMapPosX --;
			if (playerMapPosX < 0) {	//	できませんでした。
				playerMapPosX = 0;
				moved = false;
			}
			break;
		case PLAYER_DIRECTION_RIGHT : 	//	右に移動したい場合
			playerMapPosX ++;
			if (playerMapPosX >= fieldMapWidth) {	//	できませんでした。
				playerMapPosX = fieldMapWidth-1;
				moved = false;
			}
			break;
		}
		if (moved) {
			//	地図上では移動できた。ので、次に、フィールドが移動可能なフィールドかどうかをチェックする。
			int idx = filedMapInt[playerMapPosY][playerMapPosX];
			char c = MAP_DEF.charAt(idx);

    		//TODO 地形に応じた戦闘背景
    		if     (c == '5') batteImage = batteImages[1];	//山
    		else if(c == 'E') batteImage = batteImages[2];	//雪
    		else if(c == '8' || c == 'K' || c == 'S')
    						  batteImage = batteImages[3];	//夕日
    		else   			  batteImage = batteImages[0];	//草原

			if (filedMapCannotMoveTxt.indexOf(c) != -1) {
				//	移動できないフィールドなので、元に戻す。
				playerMapPosX = prevx;
				playerMapPosY = prevy;
				moved = false;
			} else {
				//	移動できるフィールドだったので、移動後の地図表示を行う
				//	地図の再描写
				Bitmap bitmap = Bitmap.createBitmap(mapImage);
	    		Canvas canvas = new Canvas(mapImage);
	    		Paint paint = new Paint();
	            paint.setAntiAlias(true);
	            paint.setStyle(Paint.Style.FILL);

	            int x = 0;
	            int y = 0;
	            int i, j;
	            switch(direction) {
	            case PLAYER_DIRECTION_UP:			//	上を描写
					canvas.drawBitmap(bitmap, 0, fieldMapImageWidth, paint);
					y = playerMapPosY - 6;
					for (x = playerMapPosX - 6, i = 0; x < playerMapPosX + 7; x ++, i ++) {
    					if (isDrawableMap(x, y)) {
							canvas.drawBitmap(fldImage[filedMapInt[y][x]], i*fieldMapImageWidth, 0, paint);
    					} else {
							canvas.drawBitmap(fldImage[cannotMoveImageInt], i*fieldMapImageWidth, 0, paint);
    					}
					}
					break;
	            case PLAYER_DIRECTION_DOWN:			//	下を描写
					canvas.drawBitmap(bitmap, 0, -fieldMapImageWidth, paint);
					y = playerMapPosY + 7 - 1;
					for (x = playerMapPosX - 6, i = 0; x < playerMapPosX + 7; x ++, i ++) {
    					if (isDrawableMap(x, y)) {
							canvas.drawBitmap(fldImage[filedMapInt[y][x]], i*fieldMapImageWidth, 12*fieldMapImageWidth, paint);
    					} else {
							canvas.drawBitmap(fldImage[cannotMoveImageInt], i*fieldMapImageWidth, 12*fieldMapImageWidth, paint);
    					}
					}
					break;
	            case PLAYER_DIRECTION_LEFT:			//	左を描写
					canvas.drawBitmap(bitmap, fieldMapImageWidth, 0, paint);
					x = playerMapPosX - 6;
					for (y = playerMapPosY - 6, j = 0; y < playerMapPosY + 7; y ++, j ++) {
    					if (isDrawableMap(x, y)) {
							canvas.drawBitmap(fldImage[filedMapInt[y][x]], 0, j*fieldMapImageWidth, paint);
    					} else {
							canvas.drawBitmap(fldImage[cannotMoveImageInt], 0, j*fieldMapImageWidth, paint);
    					}
					}
					break;
	            case PLAYER_DIRECTION_RIGHT:		//	右を描写
					canvas.drawBitmap(bitmap, -fieldMapImageWidth, 0, paint);
    				x = playerMapPosX + 7 - 1;
	    			for (y = playerMapPosY - 6, j = 0; y < playerMapPosY + 7; y ++, j ++) {
    					if (isDrawableMap(x, y)) {
							canvas.drawBitmap(fldImage[filedMapInt[y][x]], 12*fieldMapImageWidth, j*fieldMapImageWidth, paint);
    					} else {
							canvas.drawBitmap(fldImage[cannotMoveImageInt], 12*fieldMapImageWidth, j*fieldMapImageWidth, paint);
    					}
	    			}
	    			break;
				}
			}

			DebugLog.printin("X = " + playerMapPosX + " Y = " + playerMapPosY);

			//マップ遷移チェック
			try{
				mapChange();
			}catch(Exception e){
				//ignore
			}

			//マップオブジェクト上でのヘルプメッセージ
			int tileNo = filedMapInt[playerMapPosY][playerMapPosX];
			String act = (String)mapActionMap.get(String.valueOf(tileNo));
			if ("CURE".equals(act)) {
				helpMsgTxt = "画面タップ = HP・SP回復";
				helpMsgTxtIndex = -2;
			} else if ("SAVE".equals(act)) {
				helpMsgTxt = "画面タップ = セーブ";
				helpMsgTxtIndex = -2;
			} else if ("WEAPON".equals(act) || "ARMOR".equals(act) || "SHIELD".equals(act)) {
				helpMsgTxt = "画面タップ = ステータスアップ";
				helpMsgTxtIndex = -2;
			} else if ("NPC1".equals(act) ||
					   "NPC2".equals(act) ||
					   "NPC3".equals(act) ||
					   "NPC4".equals(act) ||
					   "NPC5".equals(act) ||
					   "NPC6".equals(act) ||
					   "NPC7".equals(act) ||
					   "NPC8".equals(act)){
				helpMsgTxt = "画面タップ = 会話";
				helpMsgTxtIndex = -2;
			}
		}

		//マップ再作成
		this.initMapImage(new Canvas(mapImage));

		return moved;
	}

	/**
     * マップフィールドの変更をします。
	 */
	private void mapChange() throws Exception{
		Resources r = getResources();

		//TODO マップ間移動処理
		switch (map) {
			//フィールド****************************************
			case R.string.map:
				//フィールド内にある入口は全てここで制御！
				if ((playerMapPosX == 46 && playerMapPosY == 48) ||
					(playerMapPosX == 46 && playerMapPosY == 49) ||
					(playerMapPosX == 46 && playerMapPosY == 50) ||
					(playerMapPosX == 47 && playerMapPosY == 48) ||
					(playerMapPosX == 47 && playerMapPosY == 49) ||
					(playerMapPosX == 47 && playerMapPosY == 50))
				{
					//センダイへ
					map = R.string.sendai;
					//カギ所持ならばマップ変更
					if(FLAG_ITEM1 == 1)map = R.string.sendai2;
					encFlag = false;	//モンスター発生せず
					this.init(STATUS_MAP);
					playerMapPosX = 27;playerMapPosY = 29;
					helpMsgTxt = "センダイの町です。";
					helpMsgTxtIndex = -2;

				}else if((playerMapPosX == 47 && playerMapPosY == 20) ||
						 (playerMapPosX == 47 && playerMapPosY == 21)){
					//オオサキへ
					map = R.string.oosaki;
					//カギ所持ならばマップ変更
					if(FLAG_ITEM2 == 1)map = R.string.oosaki2;
					encFlag = false;	//モンスター発生せず
					this.init(STATUS_MAP);
					playerMapPosX = 28;playerMapPosY = 7;
					helpMsgTxt = "オオサキの町です";
					helpMsgTxtIndex = -2;

				}else if(playerMapPosX == 12 && playerMapPosY == 11){
					//ナナシへ
					map = R.string.nanasi;
					encFlag = false;	//モンスター発生せず
					this.init(STATUS_MAP);
					playerMapPosX = 16;playerMapPosY = 14;
					helpMsgTxt = "？？？";
					helpMsgTxtIndex = -2;

				}else if(playerMapPosX == 17 && playerMapPosY == 55){
					//レイクへ
					map = R.string.lake;
					//オーブ所持ならばマップ変更
					if(FLAG_ITEM3 == 1)map = R.string.lake2;
					encFlag = true;	//モンスター発生
					this.init(STATUS_MAP);
					playerMapPosX = 7;playerMapPosY = 5;
					helpMsgTxt = "レイク・ダンジョン";
					helpMsgTxtIndex = -2;
				}
				break;	//CAUTION!

			//センダイ****************************************
			case R.string.sendai:
			case R.string.sendai2:
				if ((playerMapPosX <=  6) ||
					(playerMapPosX >= 43) ||
					(playerMapPosY <=  6) ||
					(playerMapPosY >= 30))
				{
					encFlag = true;	//モンスター発生
					map = R.string.map;
					this.init(STATUS_MAP);
					playerMapPosX = 47;playerMapPosY = 51;
					helpMsgTxt = "フィールドに出ます。";
					helpMsgTxtIndex = -2;
				}
				break;	//CAUTION!

			//オオサキ****************************************
			case R.string.oosaki:
			case R.string.oosaki2:
				if ((playerMapPosX <=  6) ||
					(playerMapPosX >= 43) ||
					(playerMapPosY <=  6) ||
					(playerMapPosY >= 30))
				{
					encFlag = true;	//モンスター発生
					map = R.string.map;
					this.init(STATUS_MAP);
					playerMapPosX = 47;playerMapPosY = 22;
					helpMsgTxt = "フィールドに出ます。";
					helpMsgTxtIndex = -2;
				}
				break;	//CAUTION!

			//ナナシ****************************************
			case R.string.nanasi:
				if ((playerMapPosX <=  6) ||
					(playerMapPosX >= 24) ||
					(playerMapPosY <=  6) ||
					(playerMapPosY >= 17))
				{
					encFlag = true;	//モンスター発生
					map = R.string.map;
					this.init(STATUS_MAP);
					playerMapPosX = 12;playerMapPosY = 12;
					helpMsgTxt = "フィールドに出ます。";
					helpMsgTxtIndex = -2;
				}
				break;	//CAUTION!

			//レイク****************************************
			case R.string.lake:
			case R.string.lake2:
				if (playerMapPosX == 5 && playerMapPosY == 5)
				{
					encFlag = true;	//モンスター発生
					map = R.string.map;
					this.init(STATUS_MAP);
					playerMapPosX = 17;playerMapPosY = 54;
					helpMsgTxt = "フィールドに出ます。";
					helpMsgTxtIndex = -2;
				}
				break;	//CAUTION!
		}
	}

	/**
     * マップフィールドを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void map(Canvas canvas, Paint paint) {
		boolean moved = false;

		//	タッチイベント処理
		switch (TouchStatus) {
		case TouchStatus_UP:
			moved= mapMoved(PLAYER_DIRECTION_UP);
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_DOWN:
			moved= mapMoved(PLAYER_DIRECTION_DOWN);
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_LEFT:
			moved= mapMoved(PLAYER_DIRECTION_LEFT);
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_RIGHT:
			moved= mapMoved(PLAYER_DIRECTION_RIGHT);
			if(Flag_LongTouch != true) TouchStatus = -1;
			break;
		case TouchStatus_TAP:
			//	選択キーの処理
			int k = filedMapInt[playerMapPosY][playerMapPosX];
			String act = (String)mapActionMap.get(String.valueOf(k));
			android.util.Log.e(DebugLog.TAG, "map value = " + k + ":" + act);
			//	フィールド値が、アクションマップで定義されているかをチェック。
			if ("CURE".equals(act)) {
				this.hp = this.maxHp;
				this.sp = this.maxSp;
				helpMsgTxt = "HPとSPが全回復しました！";
				try {
					MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
				} catch (Exception e) {
					e.printStackTrace();
				}
				helpMsgTxtIndex = -2;
			}
			if ("SAVE".equals(act)) {
				if (save()) {
					helpMsgTxt = "保存しました。";
					try {
						MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
					} catch (Exception e) {
						e.printStackTrace();
					}
				} else {
					helpMsgTxt = "保存に失敗しました。";
				}
				helpMsgTxtIndex = -2;
			}
			//	ステータス枠を描写
			paint.setStyle(Paint.Style.STROKE);
			paint.setStrokeWidth(4);
			paint.setColor(Color.WHITE);
			canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY,displayWidth-mapMarginX*2+2,statusDrawPosY+60),10,10,paint);
			canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY+68,displayWidth-mapMarginX*2+2,statusDrawPosY+68+30),10,10,paint);

			//	ステータス枠の中を描写

	        paint.setStyle(Paint.Style.FILL);
			paint.setStrokeWidth(1);
			paint.setTextSize(drawFontSize); //drawFontSize
			String line1 = "Lv:" + level + " HP:" + hp + "/" + maxHp + " SP:" + sp + "/" + maxSp;
			canvas.drawText(line1,  mapMarginX + 10, statusDrawPosY+25, paint);

			TouchStatus = -1;

			//TODO 各種タッチイベント（マップ毎に設定）
			switch (map) {
				//センダイ****************************************
				case R.string.sendai:
				case R.string.sendai2:
					if ("NPC1".equals(act))
						/*S*/ helpMsgTxt = "「ここはセンダイの町！秘宝を求めてハンターがたくさん集まる町だ！」";
					if ("NPC2".equals(act))
						/*T*/ helpMsgTxt = "「レベルに応じて強いモンスターが出るぜっ！」";
					if ("NPC3".equals(act))
						/*U*/ helpMsgTxt = "「武器や防具はタップするだけで入手可能…」";
					if ("NPC4".equals(act))
						/*V*/ helpMsgTxt = "「秘宝はどこにあるのだろう？？」";
					if ("NPC5".equals(act))
						/*W*/ helpMsgTxt = "「レベル上げは重要だな！」";
					if ("NPC6".equals(act))
						/*X*/ helpMsgTxt = "「宿屋ではHP・SPがタダで回復できるぞっ！」";
					if ("NPC7".equals(act))
						/*Y*/ helpMsgTxt = "「北の方に町が有ると聞いたが…」";
					if ("NPC8".equals(act))
						/*Z*/ helpMsgTxt = "「俺が最初に秘宝を入手してやるっ！」";
					if ("WEAPON".equals(act)){
						if(FLAG_SENDAI_WEAPON == 0) {
							this.str = this.str + this.level + 10;
							FLAG_SENDAI_WEAPON = 1;
							helpMsgTxt = "攻撃力がアップ！";
							try {
								MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							} catch (Exception e) {
								e.printStackTrace();
							}
						} else {
							helpMsgTxt = "効果がないようだ";
						}
						helpMsgTxtIndex = -2;
					}
					if ("ARMOR".equals(act)){
						if(FLAG_SENDAI_ARMOR == 0) {
							this.def = this.def + this.level + 10;
							FLAG_SENDAI_ARMOR = 1;
							helpMsgTxt = "防御力がアップ！";
							try {
								MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							} catch (Exception e) {
								e.printStackTrace();
							}
						} else {
							helpMsgTxt = "効果がないようだ";
						}
						helpMsgTxtIndex = -2;
					}
					if ("SHIELD".equals(act)){
						if(FLAG_SENDAI_SHIELD == 0) {
							this.spd = this.spd + this.level + 10;
							FLAG_SENDAI_SHIELD = 1;
							helpMsgTxt = "素早さがアップ！";
							try {
								MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							} catch (Exception e) {
								e.printStackTrace();
							}
						} else {
							helpMsgTxt = "効果がないようだ";
						}
						helpMsgTxtIndex = -2;
					}
					if ("TREASURE".equals(act)){
						if(FLAG_ITEM2 != 1){
							helpMsgTxt = "";
							sleep(500);
							helpMsgTxt = "　　にじのしずくを手に入れた！！";
							FLAG_ITEM2 = 1;
							try {
								MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}else{
							helpMsgTxt = "…もう何も無い。";
						}
					}
					break;	//CAUTION!

				//オオサキ****************************************
				case R.string.oosaki:
				case R.string.oosaki2:
					if ("NPC1".equals(act))
						/*S*/ helpMsgTxt = "「ここはオオサキの町！！」";
					if ("NPC2".equals(act))
						/*T*/ helpMsgTxt = "「西の行き止まりが気になる…」";
					if ("NPC3".equals(act))
						/*U*/ helpMsgTxt = "「向こう岸へはどうやって行くんだ？」";
					if ("NPC4".equals(act))
						/*V*/ helpMsgTxt = "「センダイの扉の先には何が？」";
					if ("NPC5".equals(act))
						/*W*/ helpMsgTxt = "「センダイでステータスアップはしたか？」";
					if ("NPC6".equals(act))
						/*X*/ helpMsgTxt = "「センダイの…西の湖…」";
					if ("NPC7".equals(act))
						/*Y*/ helpMsgTxt = "「古い言い伝え…」";
					if ("NPC8".equals(act))
						/*Z*/ helpMsgTxt = "「オーブを捧げると…」";
					if ("TREASURE".equals(act)){
						if(FLAG_ITEM3 != 1){
							helpMsgTxt = "";
							sleep(500);
							helpMsgTxt = "　　オーブを手に入れた！！";
							FLAG_ITEM3 = 1;
							try {
								MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							} catch (Exception e) {
								e.printStackTrace();
							}
						}else{
							helpMsgTxt = "…もう何も無い。";
						}
					}
					break;	//CAUTION!

				//レイク****************************************
				case R.string.lake:
				case R.string.lake2:
					if ("NPC1".equals(act))
						/*S*/ helpMsgTxt = "「…ヒホウハオレノモノダッ！！」";
					if ("TREASURE".equals(act) && FLAG_BOSS1 == 1){
						helpMsgTxt = "";
						sleep(500);
						helpMsgTxt = "　　伝説の秘宝を手に入れた！！";
						try {
							MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
							setStatus(STATUS_ENDING, true);
							init(STATUS_ENDING);
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
					if ("TREASURE".equals(act) && FLAG_BOSS1 == 0){
						FLAG_BOSS1 = 1;//ボスキャラフラグ
						TouchStatus = -1;
						setStatus(STATUS_BATTLE, true);//	戦闘シーンへ
					}
					break;

				case R.string.nanasi:
					helpMsgTxt = "…怪しい！";
					if (playerMapPosX == 15 && playerMapPosY == 10){
						if ("GRASS".equals(act)){
							if(FLAG_ITEM1 != 1){
								helpMsgTxt = "";
								sleep(500);
								helpMsgTxt = "　　カギを手に入れた！！";
								FLAG_ITEM1 = 1;
								try {
									MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);
								} catch (Exception e) {
									e.printStackTrace();
								}
							}else{
								helpMsgTxt = "…もう何も無い。";
							}
						}
					}
					break;	//CAUTION!
			}
		}

		//	地図の描写
		try {
			canvas.drawBitmap(mapImage, mapMarginX, mapMarginY, paint);
		} catch (Exception e) {
			e.printStackTrace();
			android.util.Log.e(DebugLog.TAG, "map map" + playerMapPosY + ", " + playerMapPosX + ", " + fieldMapWidth + ", " + fieldMapHeight);
			sleep(2000);
		}

		try {
			//	プレイヤーの描写（必ず中央）
			canvas.drawBitmap(playerImage[playerDirection][playerDrawIndex], playerDrawPosX, playerDrawPosY, paint);

			//	ステータス枠を描写
			paint.setStyle(Paint.Style.STROKE);
			paint.setStrokeWidth(4);
			paint.setColor(Color.WHITE);
			canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY,displayWidth-mapMarginX*2+2,statusDrawPosY+60),10,10,paint);
			canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY+68,displayWidth-mapMarginX*2+2,statusDrawPosY+68+30),10,10,paint);

			//	ステータス枠の中を描写

	        paint.setStyle(Paint.Style.FILL);
			paint.setStrokeWidth(1);
			paint.setTextSize(drawFontSize); //drawFontSize
			String line1 = "Lv:" + level + " HP:" + hp + "/" + maxHp + " SP:" + sp + "/" + maxSp;
			canvas.drawText(line1,  mapMarginX + 10, statusDrawPosY+25, paint);

			if((hp*dngHP/maxHp)<=0.3){
				//	ステータス枠を描写
				android.util.Log.e(DebugLog.TAG, "map player");
				paint.setStyle(Paint.Style.STROKE);
				paint.setStrokeWidth(4);
				paint.setColor(Color.RED);
				canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY,displayWidth-mapMarginX*2+2,statusDrawPosY+60),10,10,paint);
				canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY+68,displayWidth-mapMarginX*2+2,statusDrawPosY+68+30),10,10,paint);

				//	ステータス枠の中を描写

		        paint.setStyle(Paint.Style.FILL);
				paint.setStrokeWidth(1);
				paint.setTextSize(drawFontSize); //drawFontSize
				line1 = "Lv:" + level + " HP:" + hp + "/" + maxHp + " SP:" + sp + "/" + maxSp;
				canvas.drawText(line1,  mapMarginX + 10, statusDrawPosY+25, paint);
			}

			paint.setTextSize(13);
			String line2 = "経験値:" + exp + " / " + nextExp + "　攻:" + str + "　防:" + def + "　速:" + spd;
			canvas.drawText(line2, mapMarginX + 10, statusDrawPosY+50, paint);

			//	ヘルプテキストを描写
			paint.setTextSize(drawFontSize);
			int idx = helpMsgTxtIndex;
			if (idx < 0) idx = 0;
			for (int i = idx, x = mapMarginX + 10; i < helpMsgTxt.length(); i ++) {
				String c = helpMsgTxt.substring(i, i+1);
				float f = paint.measureText(c);
				if (x+f >= displayWidth-mapMarginX*2-14) {
					break;
				}
				canvas.drawText(c, x, statusDrawPosY+90, paint);
				x += f;
			}
			if (count%5 == 0) {
				helpMsgTxtIndex ++;
				if (helpMsgTxtIndex >= helpMsgTxt.length()) {
					helpMsgTxtIndex = -2;
					helpMsgTxt = "";
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			android.util.Log.e(DebugLog.TAG, "map player");
		}

		if (moved) {
			//	敵の出現をランダムで設定。（encount分の1で、敵出現）
			if (encFlag == true && MyUtil.nextInt(encount) == 0){
				//	フィールドBGMを停止して、エンカウントSE鳴動
				try {
					MyUtil.PlaySound_SE(activity, MyUtil.SE_MAP_ENCOUNT);
				} catch (Exception e) {
					e.printStackTrace();
				}
				sleep(500);
				TouchStatus = -1;
				setStatus(STATUS_BATTLE, true);	//	戦闘シーンへ
				return;
			}
		}

        if (count%3 == 0) playerDrawIndex = (playerDrawIndex+1)%2;
	}

	/**
     * メニューを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void menu(Canvas canvas, Paint paint) {
		//TODO 実装されていません！
	}

	/**
     * 戦闘シーンを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	@SuppressWarnings("unchecked")
	private void battle(Canvas canvas, Paint paint) throws Exception {

		//特殊攻撃対応
		boolean damagein = false;
		if(selectFlag == true) damagein = true;

		//	戦闘アクション中は、キー操作を無効とする。
		if (battleActions.length != 0 && battleActions[0] != null) TouchStatus = -1;	//	戦闘アクションがあれば、キー操作無効
		//	タッチイベント処理
		switch (TouchStatus){
		case TouchStatus_UP:
			if(Flag_LongTouch != true) TouchStatus = -1;
			if (battleEnemySelectedIndex == -1) {
				//	敵選択中ではない場合＝戦闘メニュー選択中
				battleMenuSelectedIndex = (battleMenuSelectedIndex+2)%4;
			} else {
				//	敵選択中だったので、戦闘メニューに戻す。
				battleEnemySelectedIndex = -1;
			}
			break;
		case TouchStatus_DOWN:
			if(Flag_LongTouch != true) TouchStatus = -1;
			if (battleEnemySelectedIndex == -1) {
				//	敵選択中ではない場合＝戦闘メニュー選択中
				battleMenuSelectedIndex = (battleMenuSelectedIndex+2)%4;
			} else {
				//	敵選択中だったので、戦闘メニューに戻す。
				battleEnemySelectedIndex = -1;
			}
			break;
		case TouchStatus_LEFT		:
			if(Flag_LongTouch != true) TouchStatus = -1;
			if (battleEnemySelectedIndex == -1) {
				//	敵選択中ではない場合＝戦闘メニュー選択中
				battleMenuSelectedIndex = battleMenuSelectedIndex/2*2+(battleMenuSelectedIndex+1)%2;
			} else {
				//	敵選択中なので、敵の選択を行う
				int idx = battleEnemySelectedIndex;
				battleEnemySelectedIndex --;
				if (battleEnemySelectedIndex < 0) battleEnemySelectedIndex = enemy.length-1;
				while (enemy[battleEnemySelectedIndex].hp <= 0) {
					battleEnemySelectedIndex --;
					if (battleEnemySelectedIndex < 0) battleEnemySelectedIndex = enemy.length-1;
					if (battleEnemySelectedIndex == idx) break;
				}
			}
			break;
		case TouchStatus_RIGHT:
			if(Flag_LongTouch != true) TouchStatus = -1;
			if (battleEnemySelectedIndex == -1) {
				//	敵選択中ではない場合＝戦闘メニュー選択中
				battleMenuSelectedIndex = battleMenuSelectedIndex/2*2+(battleMenuSelectedIndex+1)%2;
			} else {
				//	敵選択中なので、敵の選択を行う
				int idx = battleEnemySelectedIndex;
				battleEnemySelectedIndex ++;
				if (battleEnemySelectedIndex >= enemy.length) battleEnemySelectedIndex = 0;
				while (enemy[battleEnemySelectedIndex].hp <= 0) {
					battleEnemySelectedIndex ++;
					if (battleEnemySelectedIndex >= enemy.length) battleEnemySelectedIndex = 0;
					if (battleEnemySelectedIndex == idx) break;
				}
			}
			break;
		case TouchStatus_TAP:
			paint.setColor(Color.WHITE);
			//	選択キーの処理
			if (battleEnemySelectedIndex == -1) {
				//	敵選択中ではない場合＝戦闘メニュー選択中
				if (battleMenuSelectedIndex == 0) {
					//	「戦う」が選択されました。
					TouchStatus = -1;
					for (int i = 0; i < enemy.length; i ++) {
						if (enemy[i].hp > 0) {
							battleEnemySelectedIndex = i;
							break;
						}
					}
					battleMsgTxts = new String[4];
					battleMsgTxts[0] = "攻撃対象を選択してください。";
					battleMsgMasterTxts = new String[0];
					count = 1;

					selectFlag = true;//特殊攻撃対応

				} else if (battleMenuSelectedIndex == 1) {
					//	「特殊」が選択されました。
					if (sp <= reqSpec){
						battleMsgTxts = new String[4];
						battleMsgTxts[0] = "SPが足りません";
					}else {
						TouchStatus = -1;
						sp -= reqSpec;
						for (int i = 0; i < enemy.length; i ++) {
							if (enemy[i].hp > 0) {
								battleEnemySelectedIndex = i;
								break;
							}
						}
						battleMsgTxts = new String[4];
						battleMsgTxts[0] = "";
						battleMsgMasterTxts = new String[0];
						count = 1;
						damagein = true;
						paintFlag = true;
					}
				} else if (battleMenuSelectedIndex == 2) {
					//	「回復」が選択されました。
					if (sp < reqCure){
						battleMsgTxts = new String[4];
						battleMsgTxts[0] = "SPが足りません";
					}else{
						TouchStatus = -1;
						sp -= reqCure;
						for (int i = 0; i < enemy.length; i ++) {
							if (enemy[i].hp > 0) {
								battleEnemySelectedIndex = i;
								break;
							}
						}
						battleMsgTxts = new String[4];
						battleMsgTxts[0] = "";
						battleMsgMasterTxts = new String[0];
						count = 1;
						damagein = true;
					}
				} else if (battleMenuSelectedIndex == 3) {
					//	「逃げる」が選択されました。
					//	今回は、必ず、逃げれます。
					//	ただし、ボス戦時は選択不可とする！
					if(FLAG_BOSS1 != 1){
						TouchStatus = -1;
						battleEnemySelectedIndex = -1;
						sleep(500);
						setStatus(STATUS_MAP, false);	//	地図へ。
						return;
					}
				}
			//} else {
			}
			//特殊攻撃・回復対応
			if (damagein == true) {
				selectFlag = false;

				//	敵が選択されました。
				count = 1;
				//	戦闘の順番を決めます。（素早さから判断する）
				ArrayList list = new ArrayList();
				for (int i = 0; i < enemy.length; i ++) {
					list.add(enemy[i]);
				}
				Enemy player = new Enemy(this, new int[0], "ミヤギ君", hp, str, def, spd, -1, 0, 0);
				list.add(player);
				Object obj[] = list.toArray();
				Arrays.sort(obj, new EnemyComparator(null));	//	ここで、ソートされます。
				ArrayList battleActionList = new ArrayList();
				Enemy skip = null;

				//	ソートされた結果で、戦闘アクションを追加していきます。
				for (int i = 0; i < obj.length; i ++) {
					Enemy e = (Enemy)obj[i];
					if (e == player) {
						//	自分の番になった場合の処理

						//戦う
						if(battleMenuSelectedIndex == 0){
							int idx = battleEnemySelectedIndex;
							int damage = enemy[idx].getAttackDamage(player);
							battleActionList.add("MESSAGE:ミヤギ君の攻撃");
							battleActionList.add("SLEEP:500");
							battleActionList.add("ATTACK:" + idx + ":"+damage+":"
												+ enemy[idx].name + "に、\n"
												+ damage + "のダメージを与えた！");
							battleActionList.add("SLEEP:500");
							int enemyHp = enemy[idx].hp - damage;
							if (enemyHp <= 0) {
								enemy[idx].skip = true;
								//	敵を倒した！！
								battleActionList.add("MESSAGE:"+ enemy[idx].name + "を倒した！");
							}

						//特殊攻撃
						}else if(battleMenuSelectedIndex == 1){
							battleActionList.add("MESSAGE:ミヤギ君の特殊攻撃");
							battleActionList.add("SLEEP:500");
							for(int l = 0; l < enemy.length; l++){
								if(enemy[l].hp <= 0){
									continue;
								}else{
									int damage2 = enemy[l].getAttackDamage(player);
									battleActionList.add("MAGIC:" + l + ":"+damage2+":"
														+ enemy[l].name + "に、\n"
														+ damage2 + "のダメージを与えた！");
									battleActionList.add("SLEEP:500");
									int enemyHp2 = enemy[l].hp - damage2;

									if (enemyHp2 <= 0) {
										enemy[l].skip = true;
										//	敵を倒した！！
										battleActionList.add("MESSAGE:"
														+ enemy[l].name + "を倒した！");
									}
								}
							}

						//回復行動
						}else if(battleMenuSelectedIndex == 2){
							battleActionList.add("MESSAGE:ミヤギ君の回復");
							battleActionList.add("SLEEP:500");
							battleActionList.add("RECOVER:");
							battleActionList.add("MESSAGE:" + "ミヤギ君はHPを回復した");
							battleActionList.add("SLEEP:500");
						}
					} else {
						//	敵の番になった場合の処理
	 					if (e.hp <= 0) continue;			//	すでに倒している敵では、処理せず。
						//else if (e.equals(skip)) continue;	//	自分の番の時に、倒した敵なので、処理せず。
	 					else if (e.skip == true) continue;
						int damage = player.getAttackDamage(e);

						battleActionList.add("MESSAGE:" + e.name + "の攻撃！");
						battleActionList.add("SLEEP:500");
						battleActionList.add("ATTACKED:" + e.idx + ":"+damage
												+ ":" + damage + "のダメージ！");
						battleActionList.add("SLEEP:500");
					}
				}

				//	敵を全部倒したかの判定
				int enemyExp = 0;
				int cnt = 0;
				for (int i = 0; i < enemy.length; i ++) {
					//if (enemy[i].hp <= 0 || enemy[i].equals(skip)) {
					if (enemy[i].hp <= 0 || enemy[i].skip == true) {
						cnt ++;
						enemyExp += enemy[i].exp;
					}
				}
				if (cnt == enemy.length) {
					battleActionList.add("MESSAGE:敵を全部倒した！\n"
												+ enemyExp + "の経験値を手に入れた！");
					battleActionList.add("SLEEP:1000");
					exp += enemyExp;
					//	レベルアップ値の決定
					if (exp >= nextExp) {
						int maxHpUp = MyUtil.nextInt(15)+5;
						int maxSpUp = MyUtil.nextInt(level)+10;
						int strUp = MyUtil.nextInt(5)+2;
						int defUp = MyUtil.nextInt(5)+2;;
						int spdUp = MyUtil.nextInt(5)+2;
						maxspup = maxSpUp;
						battleActionList.add("MESSAGE:レベルアップ！！！");
						battleActionList.add("SLEEP:1000");
						battleActionList.add("LEVELUP:" + maxHpUp + "." + strUp + "." + defUp + "." + spdUp
												+ ":最大HP・SPが" + maxHpUp + "・"+ maxSpUp + "アップ！"
												+ "\n攻撃力が、"+ strUp + "アップ！"
												+ "\n防御力が、"+ defUp + "アップ！"
												+ "\n素早さが、"+ spdUp + "アップ！");
						battleActionList.add("SLEEP:1000");
					}
					battleActionList.add("FINISH:");
				} else {
					battleActionList.add("CLEAR:");
				}
				battleActions = MyUtil.a2s(battleActionList);
			}
		}

		if (count%5 == 0) {
			if (battleActions.length != 0 && battleActions[0] != null) {
				//	戦闘アクションごとに処理を行っていく。
				String action = battleActions[0];
				if (action.startsWith("ATTACK:")) {				//	「攻撃した」
					battleMsgTxts = new String[4];
					String msgs[] = MyUtil.split(action.substring(action.lastIndexOf(":")+1), "\n");
					for (int i = 0; i < battleMsgTxts.length; i ++) {
						if (i < msgs.length) battleMsgTxts[i] = msgs[i];
					}
					String acts[] = MyUtil.split(action, ":");
					int idx = Integer.parseInt(acts[1]);
					int damage = Integer.parseInt(acts[2]);
					int enemyHp = enemy[idx].setDamage(damage);
					if (enemyHp <= 0) {
			        	android.util.Log.e(DebugLog.TAG, "Done ![" + enemyHp + "]");
					}
					MyUtil.PlaySound_SE(activity, MyUtil.SE_BATTLE_ATTACK_PLAYER);

				}else if(action.startsWith("MAGIC:")){
					//特殊攻撃
					battleMsgTxts = new String[4];
					String msgs[] = MyUtil.split(action.substring(action.lastIndexOf(":")+1), "\n");
					for (int i = 0; i < battleMsgTxts.length; i ++) {
						if (i < msgs.length) battleMsgTxts[i] = msgs[i];
					}
					String acts[] = MyUtil.split(action, ":");
					int idx = Integer.parseInt(acts[1]);
					int damage = (int) ((double)Integer.parseInt(acts[2]) * 0.8);
					int enemyHp = enemy[idx].setDamage(damage);
					if (enemyHp <= 0) {
			        	android.util.Log.e(DebugLog.TAG, "Done ![" + enemyHp + "]");
					}
					MyUtil.PlaySound_SE(activity, MyUtil.SE_MAGIC);
					paintFlag = false;

				}else if(action.startsWith("RECOVER:")){

					//回復行動
					int recovery = (int)(maxHp * 0.8);
					if(hp + recovery > maxHp){
						hp = maxHp;
					}else{
						hp += recovery;
					}
					MyUtil.PlaySound_SE(activity, MyUtil.SE_CURE);

				} else if (action.startsWith("ATTACKED:")) {	//	「攻撃された」
					battleMsgTxts = new String[4];
					String msgs[] = MyUtil.split(action.substring(action.lastIndexOf(":")+1), "\n");
					for (int i = 0; i < battleMsgTxts.length; i ++) {
						if (i < msgs.length) battleMsgTxts[i] = msgs[i];
					}
					String acts[] = MyUtil.split(action, ":");
					int damage = Integer.parseInt(acts[2]);
					hp = hp - damage;
					MyUtil.PlaySound_SE(activity, MyUtil.SE_BATTLE_ATTACK_ENEMY);

					if (hp <= 0) {
						hp = 0;
						//	ゲームオーバーへ。
						ArrayList battleActionList = new ArrayList();
						battleActionList.add(action.substring(action.lastIndexOf(":")+1));
						battleActionList.add("SLEEP:500");
						battleActionList.add("MESSAGE:ミヤギ君は...\n力尽きた...。");
						battleActionList.add("SLEEP:1000");
						battleActionList.add("MESSAGE:ミヤギ君は...\n力尽きた...。\n\nむっ、無念だ！！！");
						battleActionList.add("SLEEP:2000");
						battleActionList.add("GAMEOVER:");
						battleActions = MyUtil.a2s(battleActionList);
			        	android.util.Log.e(DebugLog.TAG, "GAMEOVER[" + hp + "]");
					}
					canvas.drawColor(Color.RED);
					sleep(500);
				} else if (action.startsWith("MESSAGE:")) {		//	「メッセージ表示」
					battleMsgTxts = new String[4];
					String msgs[] = MyUtil.split(action.substring(action.lastIndexOf(":")+1), "\n");
					for (int i = 0; i < battleMsgTxts.length; i ++) {
						if (i < msgs.length) battleMsgTxts[i] = msgs[i];
					}
				} else if (action.startsWith("SLEEP:")) {		//	「処理一時停止」
					long sleep = Long.parseLong(action.substring(action.lastIndexOf(":")+1));
					sleep(sleep);
				} else if (action.startsWith("LEVELUP:")) {		//	「レベルアップ」
					String up[] = MyUtil.split(action, ":");
					up = MyUtil.split(up[1], ".");
					int maxHpUp = Integer.parseInt(up[0]);
					int strUp = Integer.parseInt(up[1]);
					int defUp = Integer.parseInt(up[2]);
					int spdUp = Integer.parseInt(up[3]);
					level ++;
					maxHp += maxHpUp;
					hp = maxHp;
					maxSp += maxspup;
					sp = maxSp;
					str += strUp;
					def += defUp;
					spd += spdUp;
					nextExp += 100*(level-1);
					battleMsgTxts = new String[4];
					String msgs[] = MyUtil.split(action.substring(action.lastIndexOf(":")+1), "\n");
					for (int i = 0; i < battleMsgTxts.length; i ++) {
						if (i < msgs.length) battleMsgTxts[i] = msgs[i];
					}
					MyUtil.PlaySound_SE(activity, MyUtil.SE_BATTLE_LEVELUP);
				} else if (action.startsWith("CLEAR:")) {		//	「クリア」
					battleMsgTxts = new String[4];
				} else if (action.startsWith("FINISH:")) {		//	「終了」
					TouchStatus = -1;
					battleEnemySelectedIndex = -1;
					sleep(500);
					setStatus(STATUS_MAP, false);				//	地図へ
					return;
				} else if (action.startsWith("GAMEOVER:")) {	//	「ゲームオーバー」
					TouchStatus = -1;
					battleEnemySelectedIndex = -1;
					sleep(500);
					setStatus(STATUS_GAMEOVER, true);			//	ゲームオーバーへ
					return;
				}
				DebugLog.printin("battle action[" + action + "]");
				//	戦闘アクションのスワップ（差し替え）
				for (int i = 0; i < battleActions.length-1; i ++) {
					battleActions[i] = battleActions[i+1];
					DebugLog.printin("battleActions[i]:"+battleActions[i]);
				}
				battleActions[battleActions.length-1] = null;
				count = 1;
				if (battleActions[0] == null) {
					//	元に戻る。
					battleEnemySelectedIndex = -1;
				}
			}
		}

		canvas.drawColor(Color.BLUE);
		//戦闘背景の描画
		canvas.drawBitmap(batteImage, 0, 0,paint);

		//	敵の描写
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeWidth(2);
		paint.setColor(Color.RED);
		for (int i = 0; i < enemy.length; i ++) {
			//enemy[i].drawEnemy(canvas, paint, count%4==0, i == battleEnemySelectedIndex);
			if(battleMenuSelectedIndex == 0){
				enemy[i].drawEnemy(canvas, paint, count%4==0, i == battleEnemySelectedIndex);
			}else if(paintFlag == true){
				enemy[i].drawEnemy(canvas, paint, count%4==0, true);
			}else{
				enemy[i].drawEnemy(canvas, paint, count%4==0, false);
			}
		}

		//	戦闘シーンの枠を描写
		paint.setStyle(Paint.Style.STROKE);
		paint.setStrokeWidth(4);
		paint.setColor(Color.WHITE);
		if((hp*dngHP/maxHp)<=0.4)paint.setColor(Color.RED);
		canvas.drawRoundRect(new RectF(battleMarginX+2,displayHeight/2+battleMarginY,displayWidth-battleMarginX*2+2,displayHeight/2+60+battleMarginY),10,10,paint);
		canvas.drawRoundRect(new RectF(battleMarginX+2,displayHeight/2+68+battleMarginY,displayWidth-battleMarginX*2+2,displayHeight/2+68+110+battleMarginY),10,10,paint);
		canvas.drawRoundRect(new RectF(mapMarginX+2,statusDrawPosY+68,displayWidth-mapMarginX*2+2,statusDrawPosY+68+30),10,10,paint);
		//	戦闘シーンの枠の中を描写
        paint.setStyle(Paint.Style.FILL);
		paint.setStrokeWidth(1);
		paint.setTextSize(drawFontSize);
		canvas.drawText("戦　う", battleMarginX + 50,
								displayHeight / 2 + 25 + battleMarginY, paint);

		canvas.drawText("特　殊", displayWidth / 2 + 45,
								displayHeight / 2 + 25 + battleMarginY, paint);
		canvas.drawText("回　復", battleMarginX + 50,
								displayHeight / 2 + 50 + battleMarginY, paint);
		//ボス戦時は選択不可とする！
		if(FLAG_BOSS1 != 1){
			canvas.drawText("逃げる", displayWidth / 2 + 45,
								displayHeight / 2 + 50 + battleMarginY, paint);
		}
		canvas.drawText("HP  : " + hp + "/" + maxHp,  mapMarginX + 10, statusDrawPosY + 90, paint);
		canvas.drawText("SP  : " + sp + "/" + maxSp,  mapMarginX + 150, statusDrawPosY + 90, paint);

		//	選択されている戦闘メニューの描写
		if (battleMenuSelectedIndex == 0) {
			canvas.drawText("▶", battleMarginX + 50 - battleMenuSelectedMinusX,
								  displayHeight/2 + 25 + battleMarginY, paint);
		} else if (battleMenuSelectedIndex == 1) {
			canvas.drawText("▶", displayWidth / 2 + 45 - battleMenuSelectedMinusX,
								  displayHeight / 2 + 25 + battleMarginY, paint);
		} else if (battleMenuSelectedIndex == 2) {
			canvas.drawText("▶", battleMarginX + 50 - battleMenuSelectedMinusX,
								  displayHeight / 2 + 50 + battleMarginY, paint);
		} else if (battleMenuSelectedIndex == 3) {
			//ボス戦時は選択不可とする！
			if(FLAG_BOSS1 != 1){
				canvas.drawText("▶", displayWidth / 2 + 45 - battleMenuSelectedMinusX,
								  displayHeight / 2 + 50 + battleMarginY, paint);
			}
		}

		//	戦闘メッセージの描写
		for (int i = 0, j = 0; i < battleMsgTxts.length; i ++, j ++) {
			if (battleMsgTxts[i] == null) continue;
			canvas.drawText(battleMsgTxts[i],  battleMarginX + 10,
						  displayHeight / 2 + 68 + 25 + j * 25 +battleMarginY, paint);
			DebugLog.printin("canvas.drawText:"+battleMsgTxts[i]);
		}

		if (count%5 == 0) {
			//	戦闘メッセージのスワップ（入れ替え）
			for (int i = 0; i < battleMsgTxts.length-1; i ++) {
				battleMsgTxts[i] = battleMsgTxts[i+1];
			}
			battleMsgTxtIndex ++;
			if (battleMsgTxtIndex < 0 || battleMsgTxtIndex >= battleMsgMasterTxts.length) {
				battleMsgTxts[battleMsgTxts.length-1] = null;
			} else {
				battleMsgTxts[battleMsgTxts.length-1] = battleMsgMasterTxts[battleMsgTxtIndex];
			}
		}
	}

	/**
     * ゲームオーバーを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void gameover(Canvas canvas, Paint paint) {
		//	キーイベント処理
		hp=maxHp;
		sp=maxSp;

		switch (TouchStatus) {
		case TouchStatus_TAP		:
			//	選択キーの処理
			sleep(500);
			TouchStatus = -1;
			setStatus(STATUS_TITLE, true);	//	タイトルへ
			//return;
			//TODO 強制終了した方が良い
			//System.exit(0);

		}
		//	ゲームオーバーを描写
		paint.setTextSize(42);
		paint.setColor(Color.WHITE);
		canvas.drawText("Game Over", 20, displayHeight/2-drawFontSize/2, paint);
	}

	private void ending(Canvas canvas, Paint paint) {

		//	描写位置の下限
		if (rollMsgPosY < 50) rollMsgPosY = 50;

		//	ロールメッセージを表示させます。
		paint.setTextSize(drawFontSize);
		for (int i = 0; i < rollMsgTxt.length; i ++) {
			paint.setColor(Color.WHITE);
			canvas.drawText(rollMsgTxt[i], rollMarginX, rollMsgPosY + i*(drawFontSize+5), paint);
		}
		//	ロールメッセージが、下限になった場合のみ、「Hit Key」を表示させて、次を促します。
		if (rollMsgPosY == 50) {
			paint.setColor(Color.WHITE);
			canvas.drawText("Please press Hit Key", rollMarginX, displayHeight-drawFontSize-20, paint);
			paint.setColor(Color.BLUE);
			canvas.drawText("Please press Hit Key", rollMarginX-1, displayHeight-drawFontSize-20-1, paint);
		}
		rollMsgPosY -= 5;

		switch (TouchStatus) {
		case TouchStatus_TAP		:
			//	選択キーの処理
			sleep(500);
			TouchStatus = -1;
			setStatus(STATUS_TITLE, true);	//	タイトルへ
			return;
		}
	}

	/**
	 * エラーを描写します。
	 * @param	canvas	描写キャンバスクラス
	 * @param	paint	描写ペイントクラス
	 */
	private void error(Canvas canvas, Paint paint) {
		paint.setColor(Color.WHITE);
		canvas.drawText(errorTxt, 20, 20, paint);
	}

	/**
	 * 描写処理
	 * @param	canvas	描写キャンバスクラス
	 */
	protected void onDraw(Canvas canvas) {
		if (status == STATUS_WAIT) return;

		super.onDraw(canvas);
        // 背景色の設定
        canvas.drawColor(Color.BLUE);	//DKGRAY
        // 描画オブジェクトの生成
        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);

        try {
        	//	ステータスごとに、描写を振り分ける
	        switch (status) {
	        case STATUS_TITLE:
	        	MyUtil.PlaySound_BGM(activity, MyUtil.BGM_TITLE);
				title(canvas, paint);
				break;
	        case STATUS_ROLL:
				roll(canvas, paint);
				break;
	        case STATUS_MAP:
	        	MyUtil.PlaySound_BGM(activity, MyUtil.BGM_MAP);
				map(canvas, paint);
				break;
	        case STATUS_MENU:
	        	menu(canvas, paint);
	        	break;
	        case STATUS_BATTLE:
	        	MyUtil.PlaySound_BGM(activity, MyUtil.BGM_BATTLE);
				battle(canvas, paint);
				break;
	        case STATUS_GAMEOVER:
	        	gameover(canvas, paint);
	        	break;
	        case STATUS_ENDING:
	        	ending(canvas, paint);
	        	break;
	        case STATUS_ERROR:
	        	error(canvas, paint);
	        	break;
	        default:
	        	break;
	        }
        } catch (Exception e) {
        	android.util.Log.e(DebugLog.TAG, e.toString());
        }
        count ++;
	}

	/**
	 *  画面サイズが変更されたときに呼び出されるメソッド
	 **/
    protected void onSizeChanged(int w, int h, int oldw, int oldh){
        displayWidth  = w;
        displayHeight = h;
		DebugLog.printin("onSizeChanged(" + displayWidth + ", " + displayHeight + ")");
    }

    /**
     * 保存ファイル名を返す
     * @return	保存ファイル名
     **/
    public String getFileName() {
    	return "/data/data/" + getContext().getPackageName() + "/save.txt";
    }

    /**
     * データを保存する
     * @return	保存結果
     **/
	public boolean save() {
		// 保存先の決定
		String fname = getFileName();

		StringBuffer buf = new StringBuffer();
		buf.append(level);				//	レベル
		buf.append(",");
		buf.append(maxHp);				//	最大HP
		buf.append(",");
		buf.append(hp);					//	現在のHP
		buf.append(",");
		buf.append(maxSp);				//	最大SP
		buf.append(",");
		buf.append(sp);					//	現在のSP
		buf.append(",");
		buf.append(str);				//	攻撃
		buf.append(",");
		buf.append(def);				//	防御
		buf.append(",");
		buf.append(spd);				//	素早さ
		buf.append(",");
		buf.append(exp);				//	経験値
		buf.append(",");
		buf.append(nextExp);			//	次の経験値
		buf.append(",");
		buf.append(map);				// マップ番号
		buf.append(",");
		buf.append(playerMapPosX);		//	プレイヤーのマップ上のX座標
		buf.append(",");
		buf.append(playerMapPosY);		//	プレイヤーのマップ上のY座標
		buf.append(",");

		//TODO 各種イベントフラグ
		buf.append(FLAG_SENDAI_WEAPON);
		buf.append(",");
		buf.append(FLAG_SENDAI_ARMOR);
		buf.append(",");
		buf.append(FLAG_SENDAI_SHIELD);
		buf.append(",");
		buf.append(FLAG_ITEM1);
		buf.append(",");
		buf.append(FLAG_ITEM2);
		buf.append(",");
		buf.append(FLAG_ITEM3);

		// 保存データをファイルに書き込む
		DebugLog.printin("saveToFile(" + buf.toString() + ") to [" + fname + "]");
		try {
			File file = new File(fname);
			file.getParentFile().mkdirs();

			FileOutputStream out = new FileOutputStream(file);
			out.write(buf.toString().getBytes("UTF-8"));
			out.flush();
			out.close();
			return true;
		} catch(Exception e) {
			android.util.Log.e(DebugLog.TAG, e.toString());
			return false;
		}
	}

	/**
     * データをロードする
     * @return	ロードされた情報
     **/
	public String load() {
		DebugLog.printin("load()");
		try {
			String fname = getFileName();
			DebugLog.printin("loadFromFile[" + fname + "]");
			String data = new String(MyUtil.getFileByteArray(fname), "UTF-8");
			DebugLog.printin(data);
			return data;
		} catch (Exception e) {
			android.util.Log.e(DebugLog.TAG, e.toString());
			return "";
		}
	}
}